import ReconnectingWebSocket from 'reconnecting-websocket';

// 获取userid
const userId =
  JSON.parse(window.sessionStorage.getItem('appUserInfo') || '{}')?.id || '';
// 获取域名
const baseUrl = process.env.baseUrl?.split('//')[1] || '';
class Socket {
  public static instance: Socket;
  private ws: ReconnectingWebSocket;
  private wsUrl: string = `ws://${baseUrl}allInOne/websocket/${userId}`;
  private options = {
    maxReconnectionDelay: 10000,
    minReconnectionDelay: 1000 + Math.random() * 4000,
    reconnectionDelayGrowFactor: 1.3,
    minUptime: 5000,
    connectionTimeout: 4000,
    maxRetries: Infinity,
    maxEnqueuedMessages: Infinity,
    startClosed: false,
    debug: false,
  };
  constructor() {
    this.ws = new ReconnectingWebSocket(this.wsUrl, [], this.options);
    this.wsOpen();
    this.wsError();

    this.wsMessage();
    this.wsClose();
  }

  public static getInstance() {
    if (!this.instance) {
      this.instance = new Socket();
    }
    return this.instance;
  }

  private wsOpen() {
    this.ws.addEventListener('open', () => {
      console.log('ws open');
      console.log('socket connected');
      window.dispatchEvent(new CustomEvent('wsConnected'));
      this.wsMessage();
      this.wsClose();
    });
  }

  public wsSend(msg: string) {
    console.log(`send -> ${msg}`);
    this.ws.send(msg);
  }

  private wsMessage() {
    this.ws.addEventListener('message', (e: Event) => {
      console.log(`ws -> ${e}`);
      this.sendEvent(e);
    });
  }

  private wsClose() {
    this.ws.addEventListener('close', () => {
      console.log('ws close');
      this.ws.close();
    });
  }

  private wsError() {
    this.ws.addEventListener('error', (error: any) => {
      console.log(error);
    });
  }
  private sendEvent(data: any) {
    window.dispatchEvent(
      new CustomEvent('wsMessage', {
        detail: data,
      }),
    );
  }
  /**
   * 接收ws消息
   * @param callback
   */
  public onMessage(callback?: (data: any) => void) {
    window.addEventListener('wsMessage', (e: any) => {
      callback && callback(e?.detail);
    });
  }
  /**
   * ws open 回调
   * @param callback
   */
  public connected(callback?: () => void) {
    window.addEventListener('wsConnected', () => {
      callback && callback();
    });
  }
}

export default Socket;
